package com.vision.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.vision.pojo.vo.CurrentLoginUserVO;
import com.vision.pojo.entity.Permission;
import com.vision.mapper.PermissionMapper;
import com.vision.mapper.UserFollowMapper;
import com.vision.mapper.UserMapper;
import com.vision.pojo.entity.User;
import com.vision.pojo.vo.PageVO;
import com.vision.pojo.vo.UserInfoVO;
import com.vision.service.UserService;
import com.vision.utils.*;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper; // 用户mapper

    @Autowired
    private JavaMailSender mailSender; // 邮箱发送器
    @Value("${spring.mail.username}")
    private String from; // 发送者
    @Autowired
    private PermissionMapper permissionMapper; // 权限mapper
    @Autowired
    private RedisTemplate<String,String> redisTemplate; // redis模板
    @Autowired
    private UserFollowMapper userFollowMapper; // 用户关注mapper

    /**
     * 发送验证码 给邮箱或手机
     * @param emailOrPhone 邮箱或手机号
     * @return 验证码
     */
    @Override
    public String sendVerificationCode(String emailOrPhone) throws Exception {
        String validationCode = ValidationUtils.getValidationCode(); // 获取验证码

        // 将验证码存入 redis 中
        redisTemplate.opsForValue().set(emailOrPhone, validationCode, 1, TimeUnit.MINUTES);

        if (ValidationUtils.isEmail(emailOrPhone)) {
            SimpleMailMessage simpleMailMessage = new SimpleMailMessage(); // 创建简单邮件消息
            simpleMailMessage.setFrom(from); // 设置发送人
            simpleMailMessage.setTo(emailOrPhone); // 设置收件人
            simpleMailMessage.setSubject("Vision 注册验证码"); // 设置主题
            simpleMailMessage.setText("您的验证码为：" + validationCode); // 设置内容
            mailSender.send(simpleMailMessage); // 发送邮件
        } else if (ValidationUtils.isPhone(emailOrPhone)) {
            // 发送手机验证码
            String message = AliSmsUtil.sendSms(emailOrPhone, validationCode);
            System.out.println(message);
        } else {
            throw new Exception("邮箱或手机号格式不正确");
        }
        return validationCode; // 返回验证码
    }

    /**
     * 注册
     * @param emailOrPhone 邮箱或手机号
     * @return 注册的用户信息
     */
    @Override
    public User register(String emailOrPhone) {
        User user = new User();// 创建用户
        user.setUsername(UUIDUtil.getUUID()); // 设置用户名
        user.setCreateTime(LocalDateTime.now()); // 设置创建时间
        user.setUpdateTime(LocalDateTime.now()); // 设置更新时间

        // 判断是邮箱还是手机号并设置
        if (ValidationUtils.isPhone(emailOrPhone)) {
            user.setPhone(emailOrPhone); // 设置手机号
        } else if (ValidationUtils.isEmail(emailOrPhone)) {
            user.setEmail(emailOrPhone); // 设置邮箱
        }

        userMapper.insertUserByPhoneOrEmail(user); // 插入用户
        user = userMapper.selectUserByUsername(user.getUsername()); // 查询用户 （查询用户的id）;
        return user;
    }

    /**
     * 根据手机号或邮箱查询用户
     * @param phoneOrEmail 手机号或邮箱
     * @return 用户
     */
    @Override
    public User queryUserByPhoneOrEmail(String phoneOrEmail) {
        return userMapper.selectByPhoneOrEmail(phoneOrEmail);
    }

    /**
     * 获取用户信息
     * @return 用户信息
     */
    @Override
    public CurrentLoginUserVO getCurrentLoginUser() {
        // 1. 获取 安全线程 中的用户信息
        Map<String,Integer> claims = ThreadLocalUtil.get();
        Integer id = claims.get("id");
        // 2. 查询用户信息
        User user = userMapper.selectUserById(id);
        // 3. 查询该用户的角色所拥有的权限
        List<Permission> permissions = permissionMapper.selectPermissionsByRoleId(user.getRole());
        // 4. 查询该用户的角色名
        String roleName = permissionMapper.selectRoleNameByRoleId(user.getRole());
        // 5. 查询该用户的粉丝数
        Integer fansCount = userFollowMapper.selectFansCountByUserId(user.getId());
        return getUserVO(user, roleName, fansCount, permissions);
    }

    /**
     * 获取用户信息私有方法
     * @param user 用户id
     * @return 用户信息
     */
    @NotNull
    private static CurrentLoginUserVO getUserVO(User user, String roleName, Integer fansCount, List<Permission> permissions) {
        CurrentLoginUserVO currentLoginUserVO = new CurrentLoginUserVO();
        currentLoginUserVO.setId(user.getId());
        currentLoginUserVO.setUsername(user.getUsername());
        currentLoginUserVO.setNickname(user.getNickname());
        currentLoginUserVO.setGender(user.getGender());
        currentLoginUserVO.setPhone(user.getPhone());
        currentLoginUserVO.setEmail(user.getEmail());
        currentLoginUserVO.setAvatar(user.getAvatar());
        currentLoginUserVO.setCreateTime(user.getCreateTime());
        currentLoginUserVO.setUpdateTime(user.getUpdateTime());
        currentLoginUserVO.setDescription(user.getDescription());
        currentLoginUserVO.setRoleName(roleName);
        currentLoginUserVO.setFansCount(fansCount);
        currentLoginUserVO.setRolePermission(permissions);
        return currentLoginUserVO;
    }

    /**
     * 更新用户基本信息
     * @param user 用户信息
     */
    @Override
    public void updateUserBaseInfo(User user) {
        // 1. 获取 安全线程 中的用户信息
        Integer id = getUserId();
        // 2. 设置用户信息
        user.setId(id);
        // 3. 更新用户信息
        userMapper.updateUserBaseInfo(user);
    }

    /**
     * 更新邮箱
     * @param email 邮箱
     */
    @Override
    public void updateEmail(String email) {
        // 1. 获取 安全线程 中的用户信息
        Integer id = getUserId();
        // 2. 查询邮箱
        User user = userMapper.selectUserByEmail(email);
        // 3. 判断邮箱是否已经被其他用户绑定
        if (user != null) {
            // 3. 判断邮箱是否是自己的
            if (user.getId().equals(id)) {
                throw new RuntimeException("这不是你自己的邮箱吗？");
            }
            throw new RuntimeException("该邮箱已被绑定");
        }

        // 4. 更新邮箱
        userMapper.updateEmail(id, email);
    }

    /**
     * 更新手机号
     * @param phone 手机号
     */
    @Override
    public void UpdatePhone(String phone) {
        // 1. 获取 安全线程 中的用户信息
        Integer id = getUserId();
        // 2. 查询手机号
        User user = userMapper.selectUserByPhone(phone);
        // 3. 判断手机号是否已经被其他用户绑定
        if (user != null) {
            // 3. 判断邮箱是否是自己的
            if (user.getId().equals(id)) {
                throw new RuntimeException("这不是你自己的手机号吗？");
            }
            throw new RuntimeException("该手机号已被绑定");
        }
        // 4. 更新手机号
        userMapper.updatePhone(id, phone);
    }

    /**
     * 通过 id 获取用户信息
     * @param id 用户id
     * @return 用户信息
     */
    @Override
    public User getUserById(Integer id) {
        return userMapper.selectUserById(id);
    }

    /**
     * 更新密码
     * @param id 用户id
     * @param password 密码
     */
    @Override
    public void updatePassword(Integer id, String password) {
        // 1. 加密密码
        String md5String = Md5Util.getMD5String(password);
        // 2. 更新密码
        userMapper.updatePassword(id, md5String);
    }

    /**
     * 获取用户详细信息
     * @param userId 用户id
     * @return 用户详细信息
     */
    @Override
    public UserInfoVO getUserDetailInfoById(Integer userId) {
        // 1. 查询用户信息
        User user = userMapper.selectUserById(userId);
        if (user == null) {
            throw new RuntimeException("无当前用户信息");
        }

        // 2. 查询改用户角色名
        String roleName = permissionMapper.selectRoleNameByRoleId(user.getRole());
        // 3. 查询该用户的粉丝数
        Integer fansCount = userFollowMapper.selectFansCountByUserId(user.getId());
        // 4. 封装用户信息
        UserInfoVO userInfoVO = new UserInfoVO();
        userInfoVO.setId(user.getId());
        userInfoVO.setUsername(user.getUsername());
        userInfoVO.setNickname(user.getNickname());
        userInfoVO.setEmail(user.getEmail());
        userInfoVO.setPhone(user.getPhone());
        userInfoVO.setFansCount(fansCount);
        userInfoVO.setCreateTime(user.getCreateTime());
        userInfoVO.setUpdateTime(user.getUpdateTime());
        userInfoVO.setAvatar(user.getAvatar());
        userInfoVO.setDescription(user.getDescription());
        userInfoVO.setRoleName(roleName);
        userInfoVO.setGender(user.getGender());

        // 5. 查询关注列表中是否存在该用户
        Map<String, Integer> claims = ThreadLocalUtil.get();
        Integer currentUserId = claims.get("id");
        Integer count = userFollowMapper.selectCountByUserIdAndFollowId(currentUserId,userId);
        if (count > 0) {
            userInfoVO.setIsSubscribed(count);
        } else {
            userInfoVO.setIsSubscribed(0);
        }

        // 6. 返回用户信息
        return userInfoVO;
    }

    /**
     * 获取用户列表
     * @param pageNum 页码
     * @param pageSize 每页显示的条数
     * @param nickname 昵称
     * @return 用户列表
     */
    @Override
    public PageVO<UserInfoVO> getUserList(Integer pageNum, Integer pageSize, String nickname,Integer userId) {
        // 2. 创建 pageVO
        PageVO<UserInfoVO> pageVO = new PageVO<>();
        // 3. 开启分页查询
        PageHelper.startPage(pageNum,pageSize);
        // 4. 查询用户列表
        List<UserInfoVO> list = userMapper.selectUserList(userId,nickname);
        // 5. 向下转型
        Page<UserInfoVO> userList = (Page<UserInfoVO>) list;
        // 6. 封装 pageVO
        pageVO.setItems(userList.getResult());
        pageVO.setTotal(userList.getTotal());
        pageVO.setPageNum(userList.getPageNum());
        pageVO.setPageSize(userList.getPageSize());
        // 7. 返回 pageVO
        return pageVO;
    }

    /**
     * 获取用户id
     * @return 用户id
     */
    private Integer getUserId () {
        Map<String,Object> claims = ThreadLocalUtil.get();
        return (Integer) claims.get("id");
    }
}
